from sqlalchemy import text
from public_xue import get_filename_part, history_query, history_writelog, sleep
import mysql.connector
import threading
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QApplication,QHBoxLayout,QLineEdit,QTextEdit,QDesktopWidget
from PyQt5.QtGui import QTextCursor
from PyQt5.QtCore import pyqtSignal, QObject
import pymysql
from contextlib import contextmanager
import mysql.connector
from mysql.connector import Error as MySQLError
print(mysql.connector.__version__)
import queue
import threading
from datetime import datetime, timedelta, time as datetime_time
import requests
from lxml import etree
import time
import os
import random
from random import randint
from datetime import datetime
import pytz
import re
import sys
import mysql.connector
from PyQt5.QtCore import QPoint
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtCore import Qt  # 正确导入Qt
import queue
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QPushButton
from PyQt5.QtCore import pyqtSignal, QObject
import threading
from mysql.connector import Error as MySQLError  # 正确的导入方式
print(mysql.connector.__version__)
from PyQt5.QtWidgets import QGridLayout
  

 # from white_list_cache import WhiteListCache
from datetime import datetime 
from PyQt5.QtCore import pyqtSignal, QObject
import logging
import traceback
from excelhelper_xue import excelhelper_xue
logging.basicConfig(filename=r'.\error.log', level=logging.ERROR)
from process_miaoshou1 import miaoshou_auto
from process_amazon2 import amazon_initial, amazon_capture_product
error_details=''
splitchar = '->'
print(mysql.connector.__version__)

from playwright.sync_api import sync_playwright  # 改用同步版本的 playwright
from threading import Thread
import re  # 确保导入re模块
 

def get_disk_serial_simple():
    """获取第一个硬盘序列号（简化版）"""
    try:
        import wmi
        c = wmi.WMI()
        for disk in c.Win32_DiskDrive():
            if disk.SerialNumber:
                return disk.SerialNumber.strip()
        return None
    except Exception as e:
        print(f"Error getting disk serial: {e}")
        return None

def getexcept   (emsg):
        spec = [
            "'"
            '<', '>', '$', '*', '&', '%', '.', '"', '+', '-', '@', '"', '\\',
            '(', ')', ' ', '#', '.', '//', '#'
        ]
        for sp in spec:
            if sp in emsg:
                emsg = emsg.replace(sp, ' ')
        emsg = emsg.replace('"', '')
        return emsg.strip()

def except_to_db_rpa(self,dbhelper,error_details):
        logmessage=f'-->rpa->{error_details}  {datetime.now()}'
        logmessage=getexcept(logmessage)
        logging.error("An error occurred->" + logmessage, exc_info=True)   
        self.sender.textUpdateSignal.emit(logmessage)
        sql = f" insert into crawlexcept(opdate,exceptcon)  values(now(),%s)"
        try:
            dbhelper.execute(sql,(logmessage,))
        except Exception as e:
            print('连接数据库出错',e)
class MessageSender(QObject):
    textUpdateSignal = pyqtSignal(str)
 
class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.resume_button = QPushButton("启动任务")
        self.resume_button.clicked.connect(self.resume_thread)
        self.pause_button = QPushButton("停止任务")
        self.pause_button.clicked.connect(self.pause_thread)
        self.pause_event = threading.Event()
        self.pause_event.clear()  #
        self.setGeometry(300, 300, 800, 500)
        self.setWindowTitle('跨境选品上新-RPA')
        text_layout = QHBoxLayout()
        self.textmemo = QTextEdit()
        text_layout.addWidget(self.textmemo)

        self.sender = MessageSender()
        self.sender.textUpdateSignal.connect(self.textmemo.append)
        layout_h = QHBoxLayout()

        layout_h.addWidget(self.resume_button)
        self.capture_amazon_status=True
        self.miaoshou_process_status=True

        self.btn_capture_amazon_product = QPushButton("采集亚马逊商品")
        self.btn_miaoshou_process_upload = QPushButton("妙手自动上新")  
        self.btn_capture_amazon_stop = QPushButton("停止采集亚马逊")
        self.btn_miaoshou_process_stop = QPushButton("停止妙手上新") 

        self.btn_capture_amazon_product.clicked.connect(lambda: self.delete_task_record('capture_amazon_product'))
        self.btn_miaoshou_process_upload.clicked.connect(lambda: self.delete_task_record('miaoshou_process_upload'))

        self.btn_capture_amazon_stop.clicked.connect(lambda: self.stop_task_record('capture_amazon_stop'))
        self.btn_miaoshou_process_stop.clicked.connect(lambda: self.stop_task_record('miaoshou_process_stop'))

        grid_layout = QGridLayout()
        grid_layout.addWidget(self.btn_capture_amazon_product, 0, 0)
        grid_layout.addWidget(self.btn_miaoshou_process_upload, 0, 1)
        grid_layout.addWidget(self.btn_capture_amazon_stop, 1, 0)
        grid_layout.addWidget(self.btn_miaoshou_process_stop, 1, 1)
 
 
        # self.textUpdateSignal.connect(self.textmemo.append)
        self.textmemo.append(
            '启动就可以上新数据')
        # layout_h.addWidget(self.pause_button)
        main_layout = QVBoxLayout()
        main_layout.addLayout(layout_h)
        main_layout.addLayout(text_layout)
        main_layout.addLayout(grid_layout)

        self.setLayout(main_layout)
        self.thread = []
        self.browsers= []
        self.contexts= []
        self.pages= []
 
        self.miaoshou_lock = threading.Lock()

        self.excelhelper_instance = excelhelper_xue()

  

        main_layout.addLayout(text_layout)

        self.setLayout(main_layout)
        diskid = get_disk_serial_simple()
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        diskinblacklist=history_writelog(self.excelhelper_instance,'window created',1,diskid)
        if diskinblacklist :    
            self.textmemo.append(f"{timestamp}，你的软件，没有获取授权！请联系版权所有者。")
        else:
            stations=['amazon','miaoshou']
            for station in stations:
                tis = threading.Thread(target=self.parse_capture, args=(self.sender.textUpdateSignal, diskid,station))
                self.thread.append(tis)
            
            self.resume_thread()

    def pause_thread(self):
        # self._pause_event.clear()
        ixx = 2

    def stop_task_record(self, task_name):
        """删除指定任务记录"""
        try:
            match(task_name):
                case 'capture_amazon_stop':
                    self.capture_amazon_status=False
                    self.sender.textUpdateSignal.emit(f"当前采集阶段性任务完毕，才会完全停止采集亚马逊任务")
                case 'miaoshou_process_stop':
                    self.miaoshou_process_status=False
                    self.sender.textUpdateSignal.emit(f"当前妙手上新阶段性任务完毕，才会完全停止妙手上新任务")
        except Exception as e:
            self.sender.textUpdateSignal.emit(f"停止任务失败: {str(e)}")
            logging.error(f"停止任务{task_name}失败: {str(e)}")
    def delete_task_record(self, task_name):
        """删除指定任务记录"""
 
        def _delete_in_thread(task_name):
            try:
                self.excelhelper_instance.execute(f"DELETE FROM las_task WHERE taskname = '{task_name}'")
                self.sender.textUpdateSignal.emit(f"已分配任务: {task_name}，等候10秒任务开始执行，请间隔3分钟左右分配不同任务")
            except Exception as e:
                self.sender.textUpdateSignal.emit(f"分配任务失败: {str(e)}")
                logging.error(f"分配任务{task_name}失败: {str(e)}")
            match(task_name):
                case 'capture_amazon_product':
                    self.capture_amazon_status=True
                case 'miaoshou_process_upload':
                    self.miaoshou_process_status=True
        # 创建并启动线程
        try:
            self.excelhelper_instance.execute(f"DELETE FROM las_task WHERE taskname = '{task_name}'")
            self.sender.textUpdateSignal.emit(f"已分配任务: {task_name}，等候10秒任务开始执行，请间隔3分钟左右分配不同任务")
        except Exception as e:
            self.sender.textUpdateSignal.emit(f"分配任务失败: {str(e)}")
            logging.error(f"分配任务{task_name}失败: {str(e)}")
        match(task_name):
            case 'capture_amazon_product':
                self.capture_amazon_status=True
            case 'miaoshou_process_upload':
                self.miaoshou_process_status=True
        threading.Thread(target=_delete_in_thread, args=(task_name,)).start()

            
    def parse_capture(self, textUpdateSignal, diskid,station):
        try:
            current_hour = datetime.now().hour  # 直接获取当前小时数字（0-23）
            current_minute=datetime.now().minute
            irun=0           
            textUpdateSignal.emit('开始上新自动化')
            shanghai_tz = pytz.timezone('Asia/Shanghai')
            current_time = datetime.now(shanghai_tz)
            excelhelper_instance = excelhelper_xue()
            curpath=os.getcwd()
            playchromepath=os.path.join(curpath,'chrome-win','chrome.exe')
            textUpdateSignal.emit(f'使用浏览器地址：{playchromepath}')
            if not os.path.exists(playchromepath):
                raise Exception(f"浏览器路径不存在：{playchromepath}")
            extension_path =os.path.join(curpath,'earth-plugin') 
            if not os.path.exists(extension_path):
                raise Exception(f"浏览器路径不存在：{extension_path}")
            # 验证扩展必要文件
            required_files = ['manifest.json', 'background.js']
            # for file in required_files:
            #     if not os.path.exists(os.path.join(extension_path, file)):
            #         raise Exception(f"扩展缺少必要文件：{file}")

            textUpdateSignal.emit(f'加载扩展路径：{extension_path}')
            playwright = sync_playwright().start()
                # 扩展路径（需提前解压）
                # 启动Chromium并加载扩展
            # proxyip=getproxyip()
                

            browser  = playwright.chromium.launch_persistent_context(
                executable_path=playchromepath,
                user_data_dir=curpath,
                args=[
                    f"--disable-extensions-except={extension_path}",
                    f"--load-extension={extension_path}",
                    '--kiosk',  # 极端的全屏模式参数
                    '--no-sandbox',
                    '--disable-infobars',
                    '--disable-blink-features=AutomationControlled',
                    '--disk-cache-size=0'  # 设置磁盘缓存大小为 0，禁用缓存
                ],
                headless=False
            )
            
            page_amazon = browser.pages[0]
            sleep(random.randint(1,2)*2*random.random())

            page_miaoshou =browser.new_page()
            sleep(random.randint(1,2)*0.5*random.random())
            try:                
                miaoshou_auto_instance = miaoshou_auto( textUpdateSignal,self.excelhelper_instance,diskid)

                login_result = miaoshou_auto_instance.miaoshou_login(page_miaoshou)
                if not login_result:
                    print("妙手登录失败")
            except Exception as e:
                print(f"发生异常: {type(e).__name__}")
                print(str(e))
                traceback.print_exc()
            while True:
                try:
                    # result_df = history_query(excelhelper_instance, 'miaoshou_process_upload',random.randint(500000,1210000))
                    # if   len(result_df) == 0 and self.miaoshou_process_status:
                    #     textUpdateSignal.emit(f"开始处理了。 所有商品列表页，不可以出现类目为空的记录。")
                    #     textUpdateSignal.emit(f"缩小页面，让一页可以显示10条商品信息，商品信息不被遮挡。")
                    #     history_writelog(excelhelper_instance,'miaoshou_process_upload',1,diskid)

                    #     miaoshou_auto_instance.miaoshou_process_upload(page_miaoshou,excelhelper_instance)  
                    #     timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    #     diskinblacklist=history_writelog(excelhelper_instance,'window created',1,diskid)
                    #     if diskinblacklist :    
                    #         textUpdateSignal.emit(f"{timestamp}，你的软件，没有获取授权！请联系版权所有者。")
                    #         return
                    #     current_hour = datetime.now().hour  # 直接获取当前小时数字（0-23）
                    #     current_minute=datetime.now().minute
                    #     irun=0
                    #     if current_minute%10==random.randint(2,6):
                    #         textUpdateSignal.emit(f"当前时间：{current_hour}:{current_minute}")
                    # 5. 处理采集导出
                    miaoshouurl=page_miaoshou.url
                    miaoshoutitle=page_miaoshou.title
                    add_button_selector = 'button.add-button'
                    selector = "li.scroll-menu-nav__item.is-active div"
                    if station=='miaoshou' and page_miaoshou.query_selector(selector)  :
                        with self.miaoshou_lock:
                            miaoshou_auto_instance.monitor_5_features(page_miaoshou)
                    result_df = history_query(excelhelper_instance, 'capture_amazon_product',random.randint(500000,1210000))
                    if    len(result_df) == 0 and self.capture_amazon_status and station=='amazon':
                        # client = page_amazon.context.new_cdp_session(page_amazon)
                        # client.send("Network.enable")
                        # client.send("Network.emulateNetworkConditions", {
                        #     "offline": False,
                        #     "downloadThroughput": 500 * 1024 / 8,  # 500 kb/s
                        #     "uploadThroughput": 250 * 1024 / 8,    # 250 kb/s
                        #     "latency": 40  # ms
                        # })
                        # client.send("Runtime.enable")
                        # client.on("Runtime.consoleAPICalled", lambda params: print("Console message:", params))

                        page_amazon.goto("https://www.amazon.com/")
                        
                        page_amazon.evaluate("""
                                window.scrollTo(0, document.body.scrollHeight);
                                setTimeout(() => {
                                    window.scrollTo(0, 0);
                                }, 2000);   
                            """)

                        if random.random()<0.1:
                            amazon_login_result = amazon_initial(page_amazon)
                            if not amazon_login_result:
                                print("亚马逊初始化失败")

                        sleep(1)
                        sql=f"select * from app_product_xue where  can_pubished=1 and 1=2 and capturedatetowalmart is null limit 3"
                        rows=excelhelper_instance.query_one(sql)
                        asins=''
                        asin_list=[]
                        for index,  row in enumerate(rows):
                            # 处理可能包含地区名称的字段
                            try:

                                print(row['productid'])
                                asin=row['productid']
                                
                                asin=row['productid']
                                asin_list.append({'asin':asin })
                                asins=asins + f"'{asin}',"
                                sleep(0.2*random.random())
                                print(datetime.now(),asin,index+1,'加入到妙手完成')
                            except Exception as e:
                                print(f"发生异常: {type(e).__name__}")
                                print(str(e))
                                traceback.print_exc()
                        capture_result=[]   
                        asins=asins[:-1]
                        sql='update app_product_xue set capturedatetowalmart=now() where productid in ('+asins+')'
                        sqllist=[]
                        
                        if len(asin_list)>0:
                            for index,  asin in enumerate(asin_list):
                                if self.capture_amazon_status==False:
                                    break
                                dt1=datetime.now()
                                capture_result.append(amazon_capture_product(page_amazon,asin['asin']))
                                asinx=asin['asin']
                                positions = random.sample(range(len(asinx)), 2)
                                dtx=datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                                s_list = list(asinx)
                                for pos in positions:
                                    s_list[pos] = '-'
                                asinx= ''.join(s_list)
                                dt2=datetime.now()
                                time_diff = dt2 - dt1
                                textUpdateSignal.emit(f"{dtx}:进度{index+1}/{len(asin_list)},采集产品：{asinx},耗时{time_diff.total_seconds()}秒")
                            sql='update app_product_xue set opdate=now() where productid in ('+asins+')'
                            sqllist=[{'query':sql,'params':[]}]
                            cs2=[]
                            sql=''' insert into app_product_xue (productid,detail1,detail2,detail3,detail4,detail5,opdate)
                                select :asin,:detail1,:detail2,:detail3,:detail4,:detail5,now()  on duplicate key update opdate=now(),
                                detail1=values(detail1),detail2=values(detail2),detail3=values(detail3),detail4=values(detail4),detail5=values(detail5)                                
                            '''
                            for cs in capture_result:
                                if not cs :
                                    continue
                                cs2.append({'asin':cs['asin'],'detail1':cs['detaillist'][0],'detail2':cs['detaillist'][1], 'detail3':cs['detaillist'][2] ,'detail4':cs['detaillist'][3],'detail5':cs['detaillist'][4],  'image_url':cs['image_url']})
                            sqllist.append({'query':sql,'params':cs2})                
                        alen=len(asin_list)

                        sql=f"select * from app_asinsupload_xue where   processdate is null limit 3"
                        rows=excelhelper_instance.query_one(sql)
                        asins=''
                        asin_list=[]
                        for index,  row in enumerate(rows):
                            # 处理可能包含地区名称的字段
                            try:

                                print(row['asin'])
                                asin=row['asin']
                                asin_list.append({'asin':asin })
                                asins=asins + f"'{asin}',"
                            except Exception as e:
                                print(f"发生异常: {type(e).__name__}")
                                print(str(e))
                                traceback.print_exc()
                        asins=asins[:-1]
                        blen=len(asin_list)
                        if alen+blen==0:
                            sql="UPDATE app_asinsupload_xue SET processdate = NULL WHERE LENGTH(IFNULL(detail1,'')) + LENGTH(IFNULL(detail2,'')) < 10"
                            self.excelhelper_instance.execute(sql)
                            history_writelog(excelhelper_instance,'capture_amazon_product',1,diskid)
                            textUpdateSignal.emit(f"检查是否采集完毕，请进入http://43.134.229.114:8000/admin 查看五点是否采集正常")
                            textUpdateSignal.emit(f":进度,:初次采集完毕，如果有发现有异常采集的，需要再人工采集!")

                        for index,  asin in enumerate(asin_list):
                            # page_amazon.close()
                            # page_amazon = browser.new_page()
                            dt1=datetime.now()

                            res=amazon_capture_product(page_amazon,asin['asin'])
                            asinx=asin['asin']
                            positions = random.sample(range(len(asinx)), 3)
                            dtx=datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                            s_list = list(asinx)
                            for pos in positions:
                                s_list[pos] = '*'
                            asinx= ''.join(s_list)
                            dt2=datetime.now()
                            time_diff = dt2 - dt1
                            textUpdateSignal.emit(f"{dtx}:进度{index+1}/{len(asin_list)},采集产品：{asinx},耗时{time_diff.total_seconds()}秒")
                            capture_result.append(res)
                        
                        if len(asins)>5:
                            sql='update app_asinsupload_xue set processdate=now() where asin in ('+asins+')'
                            sqllist.append({'query':sql,'params':[]})
                        sql=''' insert into app_asinsupload_xue (asin,detail1,detail2,detail3,detail4,detail5,opdate,processdate,image_url)
                                select :asin,:detail1,:detail2,:detail3,:detail4,:detail5,now(),now(),:image_url  on duplicate key update opdate=now(),
                                processdate=now(),
                                detail1=values(detail1),detail2=values(detail2),detail3=values(detail3),
                                detail4=values(detail4),detail5=values(detail5),image_url=values(image_url) 
                                
                            ''' 
                        cs2=[]
                        if len(capture_result)>0:
                            for cs in capture_result:
                                try:
                                    cs2.append({'asin':cs['asin'],'detail1':cs['detaillist'][0],'detail2':cs['detaillist'][1], 'detail3':cs['detaillist'][2] ,'detail4':cs['detaillist'][3],'detail5':cs['detaillist'][4],  'image_url':cs['image_url']})
                                except Exception as e:
                                    print(capture_result)
                                    print(f"发生异常: {type(e).__name__}")
                                    print(str(e))
                                    traceback.print_exc()
                            sqllist.append({'query':sql,'params':cs2})
                        if len(sqllist)>0:
                            excelhelper_instance.execute_multi(sqllist)


                except Exception as e:
                    print(str(e))
                    traceback.print_exc()     
                waittime1=random.randint(2,3) * (0.1+random.random()) 
                sleep(waittime1)
                timestamp=datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                if random.random()<0.1:
                    textUpdateSignal.emit(f"{timestamp},等待{waittime1}秒后继续下一轮")

        except Exception as e:
            print(f"发生异常: {type(e).__name__}")
            print(str(e))
            traceback.print_exc()

    def resume_thread(self):
        # 简化线程启动逻辑
        thread = Thread(target=self.parse_capture, args=(self.sender.textUpdateSignal, get_disk_serial_simple()))
        thread.start()
        self.thread.append(thread)
        self.resume_button.setEnabled(False)

    def getexcept   (self,emsg):
        spec = [
            "'"
            '<', '>', '$', '*', '&', '%', '.', '"', '+', '-', '@', '"', '\\',
            '(', ')', ' ', '#', '.', '//', '#'
        ]
        for sp in spec:
            if sp in emsg:
                emsg = emsg.replace(sp, '')
        emsg = emsg.replace('"', '')
        return emsg.strip()
    def get_configure( self):
            
        result = self.dbhelper.query("SELECT * FROM configure")
        return result

def optimize_page_display(page):
    # 1. 最大化窗口
    page.evaluate("""
        window.moveTo(0, 0);
        window.resizeTo(
            window.screen.availWidth,
            window.screen.availHeight
        );
    """)
    
    # 2. 隐藏自动测试提示
    page.add_init_script("""
        Object.defineProperty(navigator, 'webdriver', {
            get: () => false,
        });
        
        // 移除可能的提示条
        setTimeout(() => {
            const infobars = document.querySelectorAll('div[data-infobars]');
            infobars.forEach(bar => bar.remove());
        }, 1000);
    """)
    
    # 3. 修改表格CSS以确保完整显示
    page.add_style_tag(content="""
        .jx-pro-virtual-table__wrapper {
            width: 100% !important;
            overflow-x: visible !important;
        }
        .jx-pro-virtual-table {
            width: 100% !important;
            min-width: 1600px !important;
        }
        .el-table__body-wrapper {
            overflow-x: visible !important;
        }
    """)
    
    # 4. 如有必要，调整网页缩放比例
    page.evaluate("document.body.style.zoom = '50%'")
    
    return True

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Window()
    win.show()
    sys.exit(app.exec_())
